import socket
import select
import packet
import shutil
import os
import client_loop
import urllib
from parser.parser import Presentation

class Client:
	# erori pe care le poate genera clientul
	E_SIMPLY_QUIT		= 0
	E_SERVER_ADDRESS 	= 1
	E_AUTH_REJECTED 	= 2
	E_KICKED_OUT		= 3

	list_downloaded		= []


	def __init__(self, verbose):
		self.int_port				= 50000 # port is hardcoded
		self.bool_authenticated 	= False
		self.bool_got_presentation 	= False
		self.bool_verbose 			= verbose
		self.int_pres_slide			= -1
		self.last_error				= None
		self.pres_parser 			= Presentation("<presentation/>", False, self)
		self.bool_exit				= False
		return


	def connect(self, disp, server, name, password):
		# display object
		self.parent	= disp
		
		# server connection
		try:
			self.sock_remote = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
			self.sock_remote.settimeout(2)
			self.sock_remote.connect((server, self.int_port))
			if self.bool_verbose: print "Server contacted. Authenticating..."
		except:
			if self.bool_verbose: print "Error connecting to server. Check server ip address."
			self.last_error = (self.E_SERVER_ADDRESS, "Could not connect to server. Check server ip address.")
			if self.parent is not None: 
				self.parent.display_error("Could not connect to server. Check server ip address.")

			return
		
		# server authentication
		str_authpacket = packet.encode_client_packet('auth', (name, password))
		self.sock_remote.send(str_authpacket)
		if self.bool_verbose: print "Authentication sent."

#	def client_loop(self):
#		inputready,outputready,exceptready = select.select([self.sock_remote],[],[],.5)					
#		
#		if self.sock_remote in inputready:
#			var_result = packet.receive_packet(self.sock_remote, False)
#			if var_result is not None:
#				tup_error = self.parse_packet(var_result)
#				if tup_error is not None:
#					return tup_error
#		
#		return None

	def start_loop(self):
		self.client_loop = client_loop.Client_loop_thread(self, self.bool_verbose)
		self.client_loop.start() 

	def get_current_slide_xml(self):
	    return self.pres_parser.get_slide(self.int_pres_slide)


	# ****************************************
	#  IMPORTANT : PACKET ACTION OCCURS HERE!
	# ****************************************
	def parse_packet(self, var_result):
		# packet received
		if self.bool_verbose: 
			str_type, str_content = var_result
			#print "Packet received from server. type=", str_type, "content=", str_content
		
		tup_result = packet.decode_client_packet(var_result)
		if tup_result is not None:
			# packet recognised
			str_type, var_args = tup_result
			
			if str_type == "ares":
				# authentication result packet
				bool_accepted, str_message = var_args
				if bool_accepted:
					self.bool_authenticated = True;
					return None
				else:
					if self.bool_authenticated:
						self.bool_authenticated = False;
						# generate an error saying that we've been kicked out
						return (self.E_KICKED_OUT, str_message)
					else:
						# generate an error saying that we were not accepted
						return (self.E_AUTH_REJECTED, str_message)
			elif str_type == "pxml":
				if not self.bool_got_presentation:
					# presentation xml packet - peasentation!
					self.pres_parser = Presentation(var_args, False, self)
					self.int_pres_slide = -1				
					# display call - update display
					self.parent.display_slide(self.get_current_slide_xml())
					return None
				else:
					# presentation already received
					# simply ignore new presentation
					return None
			elif str_type == "psno":
				# presentation slide number packet
				if (self.int_pres_slide != var_args):
					self.int_pres_slide = var_args			
					# display call - update display
					self.parent.display_slide(self.get_current_slide_xml())
					return None
				else:
					#simply ignore presentation slide
					return None
			elif str_type == "mesg":
				# message packet
				# ********** not implemented yet in interface
				# self.parent.display_message(var_args)
				return None
			else:
				# unrecognised packet
				return None
		return None
		
	def get_image(self,filename,url):
		# create the directory for download
		
		try:
			os.mkdir('/tmp/'+str(os.getpid()))
		except OSError:
			pass
		
		str_current = '/tmp/'+str(os.getpid())+"/"+filename
		
		for tup_elem in self.list_downloaded:
			str_url, str_file = tup_elem
			
			if str_url == url:
				# already downloaded ...
				if str_file == str_current:
					# ... to the correct filename
					return str_current
				else:
					# ... to another file
					try:
						shutil.copyfile(str_file, str_current)
						self.list_downloaded.append((url,str_current))
					except:
						return None
					return str_current
			
		# we need to download this file
		try:
			print 'Downloading:',url,'to',str_current
			urllib.urlretrieve(url, str_current)
		except:
			print "Try to download failed"
			return None
		else:
			self.list_downloaded.append((url,str_current))
			return str_current		
	
	
	def cleanup_images(self):
		try:
			for tup_elem in self.list_downloaded[:]:
				str_url, str_file = tup_elem
				# try to delete file
				try:
					self.list_downloaded.remove(tup_elem)
					os.remove(str_file)
				except:
					pass
			os.rmdir('/tmp/'+str(os.getpid()))
		except OSError:
			pass
	
	def close_client(self):
		self.bool_exit = True
		
		
	